//
//  BiblioController.m
//  Bibliotecha
//
//  Created by Jaime Garnica on 4/16/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "BiblioController.h"


@implementation BiblioController

#pragma mark Received Actions

- (IBAction) getInfo:(id)sender
{
	[editInfo release];
	editInfo = [[GetInfo alloc] init];
	
	NSIndexSet *selectedRows = [bookView selectedRowIndexes];
	
	if( [selectedRows count] == 1)
	{
		if( [bookView selectedRow] != -1 )
		{
			[editInfo initWithLibrary:theLibrary andBook:[[theLibrary books] 
														  objectAtIndex:[bookView selectedRow]+1]];
		}
	}
	
	else if( [selectedRows count] > 1 )
	{
		NSArray *tempBooks = [theLibrary books];
		NSRange theRange;
		theRange.location = 1;
		theRange.length = [tempBooks count]-1;
		tempBooks = [tempBooks subarrayWithRange:theRange];
		
		NSArray *selectedBooks = [tempBooks objectsAtIndexes:selectedRows];
		[editInfo initWithLibrary:theLibrary andBooks:selectedBooks];
	}
}


- (IBAction)openLibrary:(id)sender
{	
	int result;
    NSOpenPanel *oPanel = [NSOpenPanel openPanel];
	NSArray *fileTypes = [NSArray arrayWithObject:@"xml"];
	
    [oPanel setAllowsMultipleSelection:NO];
	[oPanel setCanChooseFiles:YES];
	[oPanel setCanChooseDirectories:NO];
	
    result = [oPanel runModalForDirectory:NSHomeDirectory()
									 file:nil types:fileTypes];
    if (result == NSOKButton)
	{
		NSString *checkFile = [[oPanel filenames] objectAtIndex:0];
		NSData *tempFile = [NSData dataWithContentsOfFile: checkFile];
		NSXMLDocument *tempXML = [[NSXMLDocument alloc] initWithData:tempFile options:0 error:nil];
		
		if( ![[[tempXML rootElement] name] isEqualToString:@"library"] )
		{
			NSAlert *alert = [[NSAlert alloc] init];
			[alert addButtonWithTitle:@"OK"];
			[alert setMessageText:@"Not a valid library.xml file"];
			[alert setAlertStyle:NSWarningAlertStyle];
			[alert runModal];
			[alert release];
		}
		
		else
		{
			[theLibrary setLibraryPath:[checkFile stringByDeletingLastPathComponent]];
			[theLibrary loadLibraryFile];
			[self fillColumns];
			[document setDocument:nil];
			[theLibrary setCurrentBook:nil];
		}
		[tempXML release];
    }
}


- (IBAction)newLibrary:(id)sender
{
	NSFileManager *fileSystem = [NSFileManager defaultManager];
	
	int result;
    NSOpenPanel *oPanel = [NSOpenPanel openPanel];
	
    [oPanel setAllowsMultipleSelection:NO];
	[oPanel setCanChooseFiles:NO];
	[oPanel setCanChooseDirectories:YES];
	
    result = [oPanel runModalForDirectory:NSHomeDirectory()
									 file:nil types:nil];
    if (result == NSOKButton) 
	{
        NSArray *path = [oPanel filenames];
		NSString *checkFile = [path objectAtIndex:0];
		checkFile = [checkFile stringByAppendingString:@"/library.xml"];
		
		if( [fileSystem isReadableFileAtPath:checkFile] )
		{
			NSAlert *alert = [[NSAlert alloc] init];
			[alert addButtonWithTitle:@"OK"];
			[alert setMessageText:@"Library file already exists in this location"];
			[alert setAlertStyle:NSWarningAlertStyle];
			[alert runModal];
			[alert release];
		}
		
		else
		{
			[theLibrary setLibraryPath:[path objectAtIndex:0]];
			[theLibrary createLibraryFile];
			[self fillColumns]; 
			[document setDocument:nil];
			[theLibrary setCurrentBook:nil];
		}
    }
}


- (IBAction)consolidateLibrary:(id)sender
{
}


- (IBAction)openPreferences:(id)sender
{
	[editPreferences initPrefs];
}


- (IBAction)showInFinder:(id)sender
{
	if( [[bookView selectedRowIndexes] count] == 1 )
	{
		NSString *selectedBook = [[theLibrary books] objectAtIndex:[bookView selectedRow]+1];
		NSString *path = [theLibrary libraryPath];
		path = [path stringByAppendingString:[[theLibrary returnBook:selectedBook] objectAtIndex:8]];
		
		[[NSWorkspace sharedWorkspace] selectFile:path inFileViewerRootedAtPath:[path stringByDeletingLastPathComponent]]; //magic show in finder command
	}
}


- (IBAction)openDoc:(id)sender
{
    int result;
    NSArray *fileTypes = [NSArray arrayWithObject:@"pdf"];
    NSOpenPanel *oPanel = [NSOpenPanel openPanel];
	
    [oPanel setAllowsMultipleSelection:YES];
    result = [oPanel runModalForDirectory:NSHomeDirectory()
									 file:nil types:fileTypes];
    if (result == NSOKButton) 
	{
        NSArray *filesToOpen = [oPanel filenames];
		
		int i, count = [filesToOpen count];
        for (i=0; i<count; i++) 
		{
            NSString *theFile = [filesToOpen objectAtIndex:i];
            [theLibrary insertNewBookWithName:[theFile lastPathComponent] atPath:theFile];
        }
		[theLibrary saveLibraryFile];
		[typeView reloadData];
		[bookView reloadData];
		[bookView deselectAll:nil];
    }
}


- (IBAction)removeBook:(id)sender
{	
	NSIndexSet *selectedRows = [bookView selectedRowIndexes];
	
	if( [selectedRows count] == 1 )
	{
		NSAlert *alert = [[NSAlert alloc] init];
		[alert addButtonWithTitle:@"OK"];
		[alert addButtonWithTitle:@"Cancel"];
		NSString *bookToRemove = [[theLibrary books] objectAtIndex:[bookView selectedRow]+1];
		[alert setMessageText:[[@"Are you sure you want to move \"" stringByAppendingString:bookToRemove] stringByAppendingString:@"\" to the trash?"]];
		[alert setAlertStyle:NSCriticalAlertStyle];
		
		int i = [alert runModal];
		
		if( i == NSAlertFirstButtonReturn )
		{
			[theLibrary removeBook:bookToRemove toTrash:YES];
			[document setDocument:nil]; //blank out the pdfview since the pdf was just trashed
			[theLibrary setCurrentBook:nil];
		}
		
		[alert release];
		[theLibrary saveLibraryFile];  //library modified, so save it!
		[self fillColumns];
		[bookView deselectAll:nil];
	}
	
	else if( [selectedRows count] > 1 )
	{
		NSAlert *alert = [[NSAlert alloc] init];
		[alert addButtonWithTitle:@"OK"];
		[alert addButtonWithTitle:@"Cancel"];
		[alert setMessageText:@"Are you sure you want to move these books to the trash?"];
		[alert setAlertStyle:NSCriticalAlertStyle];
		
		NSArray *booksToRemove = [theLibrary books];
		NSRange theRange;
		theRange.location = 1;
		theRange.length = [booksToRemove count]-1;
		
		booksToRemove = [[booksToRemove subarrayWithRange:theRange] objectsAtIndexes:selectedRows];
		
		int i = [alert runModal];
		
		if( i == NSAlertFirstButtonReturn )
		{
			for( int j=0; j<[booksToRemove count]; j++)
			{
				[theLibrary removeBook:[booksToRemove objectAtIndex:j] toTrash:YES];
				[document setDocument:nil]; //blank out the pdfview since the pdf was just trashed
				[theLibrary setCurrentBook:nil];
			}
		}
		[alert release];
		[theLibrary saveLibraryFile];  //library modified, so save it!
		[self fillColumns];
		[bookView deselectAll:nil];
	}
}


- (IBAction)synchronize:(id)sender
{
	[theLibrary synchronizeLibraries];
}
	


- (IBAction)openSyncLibrary:(id)sender
{
	int result;
    NSOpenPanel *oPanel = [NSOpenPanel openPanel];
	NSArray *fileTypes = [NSArray arrayWithObject:@"xml"];
	
    [oPanel setAllowsMultipleSelection:NO];
	[oPanel setCanChooseFiles:YES];
	[oPanel setCanChooseDirectories:NO];
	
    result = [oPanel runModalForDirectory:NSHomeDirectory() file:nil types:fileTypes];
    if (result == NSOKButton)
	{
		NSString *checkFile = [[oPanel filenames] objectAtIndex:0];
		NSData *tempFile = [NSData dataWithContentsOfFile: checkFile];
		NSXMLDocument *tempXML = [[NSXMLDocument alloc] initWithData:tempFile options:0 error:nil];
		
		if( ![[[tempXML rootElement] name] isEqualToString:@"library"] )
		{
			NSAlert *alert = [[NSAlert alloc] init];
			[alert addButtonWithTitle:@"OK"];
			[alert setMessageText:@"Not a valid library.xml file"];
			[alert setAlertStyle:NSWarningAlertStyle];
			[alert runModal];
			[alert release];
		}
		
		else
		{
			[theLibrary setBigLibraryPath:[checkFile stringByDeletingLastPathComponent]];
			[theLibrary loadBigLibraryFile];
		}
		[tempXML release];
    }
}
	


- (IBAction)search:(id)sender
{
	NSString *searchString = [sender stringValue];
	[theLibrary setSearch:searchString];
	[self fillColumns];
	[bookView deselectAll:nil];
}


- (IBAction)openDrawer:(id)sender 
{
	[outlineDrawer openOnEdge:NSMaxXEdge];
}


#pragma mark NSApplication Delegate Methods

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{	
	theLibrary = [[LibraryController alloc]init]; //get a library controller object
	if( ![[NSUserDefaults standardUserDefaults] objectForKey:@"libraryPath"] )
	{
		[[NSUserDefaults standardUserDefaults] setObject:@"/" forKey:@"libraryPath"]; //use root if there is no default library set
	}
	
	[theLibrary  setLibraryPath:[[NSUserDefaults standardUserDefaults] stringForKey:@"libraryPath"]]; //save the path in theLibrary
	
	if( ![theLibrary loadLibraryFile] )
	{
		[theLibrary createLibraryFile];
	}
	
	[theLibrary setSearch:@""];
	[theLibrary updateBooksOfSubject:@"" andCategory:@"" andType:@""]; //reload
	[self fillColumns];
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateColumnsAfterInfo:) name:@"InfoChanged" object:nil];
	[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(pageChanged:) 
												 name: PDFViewPageChangedNotification object: document];
	//allocate objects for viewing/editing info and setting preferences
	editPreferences = [[SetPreferences alloc] init];
	
	//[outlineDrawer setMinContentSize:NSMakeSize(100, 100)];
	//[outlineDrawer setMaxContentSize:NSMakeSize(400, 400)];
}


- (void)applicationWillTerminate:(NSNotification *)aNotification{
	[theLibrary storeCurrentDestination:document];
	[theLibrary saveLibraryFile];
}


#pragma mark NSTableView Datasource Methods

- (int)numberOfRowsInTableView:(NSTableView *)aTableView{
	
	int i;
	
    if( [aTableView isEqualTo:typeView] )
	{
		[theLibrary updateTypes];
		i = [[theLibrary types] count];
	}
	
	else if( [aTableView isEqualTo:categoryView] )
	{
		NSString *type = [[theLibrary types] objectAtIndex:[typeView selectedRow]];
		[theLibrary updateCategoriesOfType:type];
		i = [[theLibrary categories] count];
	}
	
	else if( [aTableView isEqualTo:subjectView] )
	{
		[theLibrary updateSubjectsOfCategory:[[theLibrary categories] objectAtIndex:[categoryView selectedRow]]
									 andType:[[theLibrary types] objectAtIndex:[typeView selectedRow]]];
		i = [[theLibrary subjects] count];
	}
	
	else if( [aTableView isEqualTo:bookView] )
	{
		[theLibrary updateBooksOfSubject:[[theLibrary subjects] objectAtIndex:[subjectView selectedRow]]
							 andCategory:[[theLibrary categories] objectAtIndex:[categoryView selectedRow]]
								 andType:[[theLibrary types] objectAtIndex:[typeView selectedRow]]];
		i = [[theLibrary books] count]-1;
	}
	
	return i;
}


- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{	
	NSString *displayThis = [NSString stringWithString:@""];
	
	if( [aTableView isEqualTo:bookView] )
	{
		displayThis = [[theLibrary books] objectAtIndex:rowIndex+1];
	}
	
	else
	{
		if( rowIndex == 0 )
		{
			displayThis = @"All";
		}
		
		else
		{
			if( [aTableView isEqualTo:typeView] )
			{
				displayThis = [[theLibrary types] objectAtIndex:rowIndex];
			}
			
			else if( [aTableView isEqualTo:categoryView] )
			{
				displayThis = [[theLibrary categories] objectAtIndex:rowIndex];
			}
			
			else if( [aTableView isEqualTo:subjectView] )
			{
				displayThis = [[theLibrary subjects] objectAtIndex:rowIndex];
			}
			
			else
				displayThis = @"this is an outrage";
		}
	}
	return displayThis;
}


#pragma mark NSTableView Delegate Methods

- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
{
	
	if( [[aNotification object] isEqualTo:typeView] )
	{
		[typeView reloadData];
		[categoryView reloadData];
		[subjectView reloadData];
		[bookView reloadData];
	}
	
	if( [[aNotification object] isEqualTo:categoryView] )
	{
		[subjectView reloadData];
		[bookView reloadData];
	}
	
	if( [[aNotification object] isEqualTo:subjectView] )
	{
		[bookView reloadData];
	}
	
	if( [[aNotification object] isEqualTo:bookView] )
	{
		if( [theLibrary currentBook] != nil )
			[theLibrary storeCurrentDestination:document];
		
		if( [bookView selectedRow] >= 0 )
		{
			NSString *clickedBookTitle = [[theLibrary books] objectAtIndex:[bookView selectedRow]+1];
			
			[theLibrary setCurrentBook:clickedBookTitle];
			NSArray *clickedBook = [theLibrary returnBook:clickedBookTitle];
			NSString *aPath = [theLibrary libraryPath];
			aPath = [aPath stringByAppendingString:[clickedBook objectAtIndex:8]];
			
			PDFDocument *aDoc;
			aDoc = [[PDFDocument alloc] initWithURL:[NSURL fileURLWithPath:aPath]];
			[document setDocument:aDoc];
			[theLibrary setTheOutline:[aDoc outlineRoot]];
			[documentOutline reloadData];
			[aDoc release];
			
			PDFPage *oldLocation = [[document document] pageAtIndex:[[clickedBook objectAtIndex:9] unsignedIntValue]];
			[document goToPage:oldLocation];
			[document setAutoScales:YES];
		}
		
		else
		{
			[document setDocument:nil];
			[theLibrary setCurrentBook:nil];
		}
		
	}
}


#pragma mark NSOutlineView Datasource Methods

- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
{
	if( item == nil )
	{
		return [[theLibrary theOutline] childAtIndex:index];
	}
	
	else
	{
		return [item childAtIndex:index];
	}
}


- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
	if( [item numberOfChildren] > 0 ) return YES;
	else return NO;
}


- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
	if( item == nil ) return [[theLibrary theOutline] numberOfChildren];
	else return [item numberOfChildren];
}


- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
	return [item label];
}


#pragma mark NSOutlineView Delegate Methods

- (void)outlineViewSelectionDidChange:(NSNotification *)notification
{
	[document goToDestination:[[documentOutline itemAtRow:[documentOutline selectedRow]] destination]];
	
}


#pragma mark Notification Center Methods

- (void)updateColumnsAfterInfo:(NSNotification *)notification{
	[self fillColumns];
	[bookView deselectAll:nil];
}


- (void) pageChanged: (NSNotification *) notification
{
	unsigned int	newPageIndex;
	int				numRows;
	int				i;
	int				newlySelectedRow;
	
	// Skip out if there is no outline.
	if ([[document document] outlineRoot] == NULL)
		return;
	
	// What is the new page number (zero-based).
	newPageIndex = [[document document] indexForPage: [document currentPage]];
	
	// Walk outline view looking for best firstpage number match.
	newlySelectedRow = -1;
	numRows = [documentOutline numberOfRows];
	for (i = 0; i < numRows; i++)
	{
		PDFOutline	*outlineItem;
		
		// Get the destination of the given row....
		outlineItem = (PDFOutline *)[documentOutline itemAtRow: i];
		
		if ([[document document] indexForPage: [[outlineItem destination] page]] == newPageIndex)
		{
			newlySelectedRow = i;
			[documentOutline selectRow: newlySelectedRow byExtendingSelection: NO];
			break;
		}
		else if ([[document document] indexForPage: [[outlineItem destination] page]] > newPageIndex)
		{
			newlySelectedRow = i - 1;
			[documentOutline selectRow: newlySelectedRow byExtendingSelection: NO];
			break;
		}
	}
	
	// Auto-scroll.
	if (newlySelectedRow != -1)
		[documentOutline scrollRowToVisible: newlySelectedRow];
}


#pragma mark Methods

- (void)fillColumns
{	
	[typeView reloadData];
	[categoryView reloadData];
	[subjectView reloadData];
	[bookView reloadData];
}


#pragma mark Method Overrides 

-(void)dealloc
{
	[theLibrary release];
	[editInfo release];
	[super dealloc];
}

@end
